/*
 * ContactListPanel.java
 *
 * Created on 13 novembre 2007, 16:39
 */

package jtalk.view;

import java.beans.PropertyChangeEvent;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;

import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;

import jtalk.controller.DefaultController;
import jtalk.controller.Properties;
import jtalk.logging.Logger;
import jtalk.model.Contact;
import jtalk.model.Message;

/**
 *
 * @author  remy
 */
public class ContactListPanel extends jtalk.view.AbstractViewPanel {
    
    /**
	 * 
	 */
	private static final long serialVersionUID = 1554138350565726355L;

	/** Creates new form contactListPanel */
    public ContactListPanel(DefaultController ctr) {
        controller = ctr;
        chats = new HashSet<ChatFrame>();
        initComponents();
    }
    
    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
    private void initComponents() {
        contactListTree = new javax.swing.JTree();

        contactListTree.setCellRenderer(new ContactListCellRenderer());
        contactListTree.setModel(getContactListTreeModel());
        contactListTree.setRootVisible(false);
        contactListTree.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                contactListTreeMouseClicked(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(contactListTree, javax.swing.GroupLayout.DEFAULT_SIZE, 0, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(contactListTree, javax.swing.GroupLayout.DEFAULT_SIZE, 0, Short.MAX_VALUE)
        );
    }// </editor-fold>//GEN-END:initComponents

    private void contactListTreeMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_contactListTreeMouseClicked
        if(evt.getClickCount() == 2) {
        	 DefaultMutableTreeNode node = (DefaultMutableTreeNode) contactListTree.getPathForLocation(evt.getPoint().x, evt.getPoint().y).getLastPathComponent();                 
                 try {                 
                     Contact contact = (Contact)node.getUserObject();                     
                     ChatFrame chat = getChat(contact);
                     chat.setVisible(true);
                     chat.requestFocus();
                 } catch (ClassCastException e) {}
        }
    }//GEN-LAST:event_contactListTreeMouseClicked
 
    
    
    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JTree contactListTree;
    // End of variables declaration//GEN-END:variables

    @SuppressWarnings("unchecked")
	public void modelPropertyChange(PropertyChangeEvent evt) {
    	    	
    	if(evt.getPropertyName().equals(Properties.MESSAGE_IN.toString())){
    		
    		Message msg = (Message)evt.getNewValue();    		
    		ChatFrame chat = getChat(msg.getFrom());
    		
    		chat.receivedMessage(msg);
    		chat.setVisible(true);
    		
    	}else if(evt.getPropertyName().equals(Properties.CONTACT_ADD.toString())) {
    		      		    		    		    	
    		Contact contact = (Contact) evt.getNewValue();
    		
    		Logger.getLogger(this).debug("Adding contact " + contact.getName() + " in group " + contact.getGroup());    		
    		
    		//Add group
    		DefaultMutableTreeNode group = getGroupNode(contact.getGroup());
    		if(group == null) {
    			group = new DefaultMutableTreeNode(contact.getGroup(), true);
    			getContactListTreeModel().insertNodeInto(group, getContactListTreeRootNode(), getContactListTreeRootNode().getChildCount());    			
    		}
    		
    		//Add Contact
    		Enumeration enumeration = group.children();
    		while (enumeration.hasMoreElements()) {
				DefaultMutableTreeNode groupMember = (DefaultMutableTreeNode) enumeration.nextElement();
				if(groupMember.getUserObject().equals(contact)) {
					return;
				}
			}
    		getContactListTreeModel().insertNodeInto((new DefaultMutableTreeNode(contact, false)), group, group.getChildCount());    		
    		
    	}else if(evt.getPropertyName().equals(Properties.CONTACT_PRESENCE.toString())) {
    		
    		Contact contact = (Contact) evt.getNewValue();
    		DefaultMutableTreeNode contactNode = getContactNode(contact); 
    		if(contactNode != null) {
    			((Contact)contactNode.getUserObject()).setAvailable(contact.isAvailable());
    			((Contact)contactNode.getUserObject()).setStatus(contact.getStatus());
    		}else {
    			Logger.getLogger(this).debug("Contact node " + contact.getName() + " doesn't exist in contact list, cannot update presence");    			
    		}
                
                contactListTree.repaint();
    		    		    		
    	}else if(evt.getPropertyName().equals(Properties.AUTHENTICATED.toString())) {
    		if((Boolean)evt.getNewValue()) {    			
    			controller.loadContactList();
    		}else {
    			reinit();
    		}
    	}else if(evt.getPropertyName().equals(Properties.CONNECTED)) {
    		if(!(Boolean)evt.getNewValue()) {
    			reinit();
    		}
    	}
    }

	@SuppressWarnings("unchecked")
	private void reinit() {
		Logger.getLogger(this).debug("Cleaning contact list ...");
		Enumeration enumeration = getContactListTreeRootNode().children();
		while (enumeration.hasMoreElements()) {
			DefaultMutableTreeNode group = (DefaultMutableTreeNode) enumeration.nextElement();			
			getContactListTreeModel().removeNodeFromParent(group);
		}
		Logger.getLogger(this).debug("Closing chatFrame...");
		
		synchronized (chats) {		
			for(ChatFrame chat : chats) {
				chat.setVisible(false);								
			}
			chats.clear();
		}
				
	}

    @SuppressWarnings("unchecked")
	private DefaultMutableTreeNode getGroupNode(String groupName) {
    	Enumeration enumeration = contactListTreeRootNode.children();    		
    	while (enumeration.hasMoreElements()) {
    		DefaultMutableTreeNode group = (DefaultMutableTreeNode) enumeration.nextElement();
    		if(group.getUserObject().equals(groupName) && group.getAllowsChildren()) {
    			return group;
    		}
    	}
    	return null;
    }
    
    @SuppressWarnings("unchecked")
	private DefaultMutableTreeNode getContactNode(Contact contact) {
    	    	    	
    	Enumeration groupEnumeration = contactListTreeRootNode.children();    		
    	while (groupEnumeration.hasMoreElements()) {
    		DefaultMutableTreeNode group = (DefaultMutableTreeNode) groupEnumeration.nextElement();    		
    		Enumeration contactEnumeration = group.children();
    		while (contactEnumeration.hasMoreElements()) {    			
				DefaultMutableTreeNode contactNode = (DefaultMutableTreeNode) contactEnumeration.nextElement();
				if(((Contact)contactNode.getUserObject()).equals(contact)) {
					return contactNode;
				}
			}
    	}
    	return null;
    }
    
	private DefaultMutableTreeNode getContactListTreeRootNode() {
		if(contactListTreeRootNode == null) {
			contactListTreeRootNode = new DefaultMutableTreeNode("root");
		}
		return contactListTreeRootNode;
	}
	
	private DefaultTreeModel getContactListTreeModel() {
		if(contactListTreeModel == null) {
			contactListTreeModel = new DefaultTreeModel(getContactListTreeRootNode());			
			contactListTreeModel.addTreeModelListener(new TreeModelListener() {
				public void treeNodesChanged(TreeModelEvent e) {}				
				public void treeNodesRemoved(TreeModelEvent e) {}
				public void treeStructureChanged(TreeModelEvent e) {}
				
				public void treeNodesInserted(TreeModelEvent e) {					
					contactListTree.expandPath(e.getTreePath());									
					setPreferredSize(contactListTree.getMaximumSize());					
				}
				
			});
		}
		return contactListTreeModel;
	}
	
	private ChatFrame getChat(Contact contact) {
		
		Contact ct = new Contact(contact.getName().replaceFirst("/.*$", ""));
		ChatFrame chat;
		
		synchronized (chats) {
		
			for(ChatFrame c : chats) {
				if(c.getParticipant().equals(contact)) {
					if(c == null) {
						c = new ChatFrame(contact, controller);
					}
					return c;
				}
			}
			
			Logger.getLogger(this).debug("Creating new ChatFrame ...");
			
			chat = new ChatFrame(ct, controller);
			this.chats.add(chat);
			
		}
								
		return chat;
		
	}
    
    //Other variables
    private DefaultController controller;    
    private DefaultMutableTreeNode contactListTreeRootNode;
    private DefaultTreeModel contactListTreeModel;
    private Set<ChatFrame> chats;
    //End

    
}
